package TP6.implementation;

import TP2.TDA.ConjuntoTDA;
import TP2.implementation.ConjuntoTamNoAcotListaImpl1;
import TP6.NodoArista;
import TP6.NodoGrafo;
import TP6.TDA.GrafoTDA;

/**
 * Cual es la diferencia entre hacer que origen sea una lista circular o no?
 * 
 * @author Matossian
 *
 */
public class GrafoListaImpl implements GrafoTDA {
	private NodoGrafo origen;

	public void inicializar() {
		origen = null;
	}

	public void agregarVertice(int v) {
		NodoGrafo nuevo = new NodoGrafo();
		nuevo.setAristas(null);
		nuevo.setSgte(origen);
		nuevo.setValue(v);
		origen = nuevo;
	}

	public void eliminarVertice(int v) {
		NodoGrafo prev, aux;
		
		/*
		 * Elimino el nodo
		 */
		prev = getNodoPrevio(v);
		
		if(prev != null) {
			prev.setSgte(prev.getSgte().getSgte());
		} else {
			origen = origen.getSgte();
		}
		
		/*
		 * Elimino las aristas que usan el nodo eliminado
		 */
		aux = origen;
		while(aux != null) {
			eliminarArista(aux.getValue(), v);
			aux = aux.getSgte();
		}
	}

	public ConjuntoTDA vertices() {
		NodoGrafo aux = origen;
		ConjuntoTDA vertices = new ConjuntoTamNoAcotListaImpl1();
		vertices.inicializar();
		
		while(aux != null) {
			vertices.agregar(aux.getValue());
			aux = aux.getSgte();
		}
		
		return vertices;
	}

	public void agregarArista(int origen, int destino, int peso) {
		NodoGrafo nodo = getNodo(origen);
		
		NodoArista nuevaArista = new NodoArista();
		nuevaArista.setDestino(getNodo(destino));
		nuevaArista.setPeso(peso);
		nuevaArista.setSgte(nodo.getAristas());
		
		nodo.setAristas(nuevaArista);
	}

	public void eliminarArista(int origen, int destino) {
		NodoGrafo nodo = getNodo(origen);
		NodoArista aux = nodo.getAristas();
		NodoArista prev = null;
		boolean encontro = false;
		
		while(aux != null && !encontro) {
			if(aux.getDestino().getValue() == destino) {
				encontro = true;
			} else {
				prev = aux;
				aux = aux.getSgte();
			}
		}
		if(encontro) {
			if(prev != null) {
				prev.setSgte(aux.getSgte());
			} else {
				nodo.setAristas(aux.getSgte());
			}
		}
	}

	public boolean existeArista(int origen, int destino) {
		boolean existe = false;
		NodoGrafo nodo = getNodo(origen);
		NodoArista aristas = nodo.getAristas();		
		NodoArista aux = aristas;		
		
		while(aux != null && !existe) {
			if(aux.getDestino().getValue() == destino) {
				existe = true;
			}			
			aux = aux.getSgte();
		}
		
		return existe;
	}

	public int pesoArista(int origen, int destino) {
		int peso = -1;
		NodoGrafo nodo = getNodo(origen);
		NodoArista aristas = nodo.getAristas();
		
		NodoArista aux = aristas;
		
		while(aux != null) {
			if(aux.getDestino().getValue() == destino) {
				peso = aux.getPeso();
			}			
			aux = aux.getSgte();
		}
		
		return peso;
	}
	
	private NodoGrafo getNodo(int v) {
		NodoGrafo aux = origen;
		while(aux.getValue() != v) {
			aux = aux.getSgte();
		}
		return aux;
	}
	
	private NodoGrafo getNodoPrevio(int v) {
		NodoGrafo aux = origen;
		NodoGrafo prev = null;
		while(aux.getValue() != v) {
			prev = aux;
			aux = aux.getSgte();
		}
		return prev;
	}
}
